home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / common / csource.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-14  |  20.3 KB  |  772 lines

  1. /* CSource - GIMP Plugin to dump image data in RGB(A) format for C source
  2.  * Copyright (C) 1999 Tim Janik
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Library General Public
  15.  * License along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  17.  *
  18.  * This plugin is heavily based on the header plugin by Spencer Kimball and
  19.  * Peter Mattis.
  20.  */
  21.  
  22. #include "config.h"
  23.  
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27.  
  28. #include <gtk/gtk.h>
  29.  
  30. #include <libgimp/gimp.h>
  31. #include <libgimp/gimpui.h>
  32.  
  33. #include "libgimp/stdplugins-intl.h"
  34.  
  35.  
  36. typedef struct
  37. {
  38.   gchar    *file_name;
  39.   gchar    *prefixed_name;
  40.   gchar    *comment;
  41.   gboolean  use_comment;
  42.   gboolean  glib_types;
  43.   gboolean  alpha;
  44.   gboolean  use_macros;
  45.   gboolean  use_rle;
  46.   gdouble   opacity;
  47. } Config;
  48.  
  49.  
  50. /* --- prototypes --- */
  51. static void    query        (void);
  52. static void    run        (gchar   *name,
  53.                  gint     nparams,
  54.                  GimpParam  *param,
  55.                  gint    *nreturn_vals,
  56.                  GimpParam    **return_vals);
  57.  
  58. static gint    save_image    (Config  *config,
  59.                  gint32   image_ID,
  60.                  gint32   drawable_ID);
  61. static gboolean    run_save_dialog    (Config  *config);
  62.  
  63.  
  64. /* --- variables --- */
  65. GimpPlugInInfo PLUG_IN_INFO =
  66. {
  67.   NULL,  /* init_proc  */
  68.   NULL,  /* quit_proc  */
  69.   query, /* query_proc */
  70.   run,   /* run_proc   */
  71. };
  72.  
  73. Config config = 
  74. {
  75.   NULL,         /* file_name */
  76.   "gimp_image", /* prefixed_name */
  77.   NULL,         /* comment */
  78.   FALSE,        /* use_comment */
  79.   TRUE,         /* glib_types */
  80.   FALSE,        /* alpha */
  81.   FALSE,        /* use_macros */
  82.   FALSE,        /* use_rle */
  83.   100.0,        /* opacity */
  84. };
  85.  
  86. /* --- implement main (), provided by libgimp --- */
  87. MAIN ()
  88.  
  89. /* --- functions --- */
  90. static void
  91. query (void)
  92. {
  93.   static GimpParamDef save_args[] =
  94.   {
  95.     { GIMP_PDB_INT32, "run_mode", "Interactive" },
  96.     { GIMP_PDB_IMAGE, "image", "Input image" },
  97.     { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
  98.     { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
  99.     { GIMP_PDB_STRING, "raw_filename", "The name of the file to save the image in" }
  100.   };
  101.   static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]);
  102.  
  103.   gimp_install_procedure ("file_csource_save",
  104.                           "Dump image data in RGB(A) format for C source",
  105.                           "CSource cannot be run non-interactively.",
  106.                           "Tim Janik",
  107.                           "Tim Janik",
  108.                           "1999",
  109.                           "<Save>/C-Source",
  110.               "RGB*",
  111.                           GIMP_PLUGIN,
  112.                           nsave_args, 0,
  113.                           save_args, NULL);
  114.   
  115.   gimp_register_save_handler ("file_csource_save",
  116.                   "c",
  117.                   "");
  118. }
  119.  
  120. static void
  121. run (gchar   *name,
  122.      gint     nparams,
  123.      GimpParam  *param,
  124.      gint    *nreturn_vals,
  125.      GimpParam **return_vals)
  126. {
  127.   static GimpParam values[2];
  128.   GimpRunModeType  run_mode;
  129.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  130.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  131.   
  132.   run_mode = param[0].data.d_int32;
  133.   
  134.   *nreturn_vals = 1;
  135.   *return_vals  = values;
  136.   values[0].type          = GIMP_PDB_STATUS;
  137.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  138.  
  139.   if (run_mode == GIMP_RUN_INTERACTIVE &&
  140.       strcmp (name, "file_csource_save") == 0)
  141.     {
  142.       gint32 image_ID    = param[1].data.d_int32;
  143.       gint32 drawable_ID = param[2].data.d_int32;
  144.       GimpParasite *parasite;
  145.       gchar *x;
  146.       GimpImageType drawable_type = gimp_drawable_type (drawable_ID);
  147.  
  148.       gimp_get_data ("file_csource_save", &config);
  149.       config.prefixed_name = "gimp_image";
  150.       config.comment       = NULL;
  151.  
  152.       config.file_name = param[3].data.d_string;
  153.       config.alpha = (drawable_type == GIMP_RGBA_IMAGE ||
  154.               drawable_type == GIMP_GRAYA_IMAGE ||
  155.               drawable_type == GIMP_INDEXEDA_IMAGE);
  156.  
  157.       INIT_I18N_UI();
  158.  
  159.       parasite = gimp_image_parasite_find (image_ID, "gimp-comment");
  160.       if (parasite)
  161.     {
  162.       config.comment = g_strdup (parasite->data);
  163.       gimp_parasite_free (parasite);
  164.     }
  165.       x = config.comment;
  166.  
  167.       gimp_ui_init ("csource", FALSE);
  168.       export = gimp_export_image (&image_ID, &drawable_ID, "C Source", 
  169.                   (GIMP_EXPORT_CAN_HANDLE_RGB |
  170.                    GIMP_EXPORT_CAN_HANDLE_ALPHA ));
  171.       if (export == GIMP_EXPORT_CANCEL)
  172.     {
  173.       values[0].data.d_status = GIMP_PDB_CANCEL;
  174.       return;
  175.     }
  176.  
  177.       if (run_save_dialog (&config))
  178.     {
  179.       if (x != config.comment &&
  180.           !(x && config.comment && strcmp (x, config.comment) == 0))
  181.         {
  182.           if (!config.comment || !config.comment[0])
  183.         gimp_image_parasite_detach (image_ID, "gimp-comment");
  184.           else
  185.         {
  186.           parasite = gimp_parasite_new ("gimp-comment",
  187.                         GIMP_PARASITE_PERSISTENT,
  188.                         strlen (config.comment) + 1,
  189.                         config.comment);
  190.           gimp_image_parasite_attach (image_ID, parasite);
  191.           gimp_parasite_free (parasite);
  192.         }
  193.         }
  194.  
  195.       if (! save_image (&config, image_ID, drawable_ID))
  196.         {
  197.           status = GIMP_PDB_EXECUTION_ERROR;
  198.         }
  199.       else
  200.         {
  201.           gimp_set_data ("file_csource_save", &config, sizeof (config));
  202.         }
  203.     }
  204.       else
  205.     {
  206.       status = GIMP_PDB_CANCEL;
  207.     }
  208.  
  209.       if (export == GIMP_EXPORT_EXPORT)
  210.     gimp_image_delete (image_ID);
  211.     }
  212.   else
  213.     {
  214.       status = GIMP_PDB_CALLING_ERROR;
  215.     }
  216.  
  217.   values[0].data.d_status = status;
  218. }
  219.  
  220. static gboolean
  221. diff2_rgb (guint8 *ip)
  222. {
  223.   return ip[0] != ip[3] || ip[1] != ip[4] || ip[2] != ip[5];
  224. }
  225.  
  226. static gboolean
  227. diff2_rgba (guint8 *ip)
  228. {
  229.   return ip[0] != ip[4] || ip[1] != ip[5] || ip[2] != ip[6] || ip[3] != ip[7];
  230. }
  231.  
  232. static guint8 *
  233. rl_encode_rgbx (guint8 *bp,
  234.         guint8 *ip,
  235.         guint8 *limit,
  236.         guint   n_ch)
  237. {
  238.   gboolean (*diff2_pix) (guint8 *) = n_ch > 3 ? diff2_rgba : diff2_rgb;
  239.   guint8 *ilimit = limit - n_ch;
  240.  
  241.   while (ip < limit)
  242.     {
  243.       g_assert (ip < ilimit); /* paranoid */
  244.  
  245.       if (diff2_pix (ip))
  246.     {
  247.       guint8 *s_ip = ip;
  248.       guint l = 1;
  249.  
  250.       ip += n_ch;
  251.       while (l < 127 && ip < ilimit && diff2_pix (ip))
  252.         { ip += n_ch; l += 1; }
  253.       if (ip == ilimit && l < 127)
  254.             { ip += n_ch; l += 1; }
  255.       *(bp++) = l;
  256.       memcpy (bp, s_ip, l * n_ch);
  257.       bp += l * n_ch;
  258.     }
  259.       else
  260.     {
  261.       guint l = 2;
  262.  
  263.       ip += n_ch;
  264.       while (l < 127 && ip < ilimit && !diff2_pix (ip))
  265.             { ip += n_ch; l += 1; }
  266.       *(bp++) = l | 128;
  267.       memcpy (bp, ip, n_ch);
  268.       ip += n_ch;
  269.       bp += n_ch;
  270.     }
  271.       if (ip == ilimit)
  272.     {
  273.       *(bp++) = 1;
  274.       memcpy (bp, ip, n_ch);
  275.       ip += n_ch;
  276.       bp += n_ch;
  277.     }
  278.     }
  279.  
  280.   return bp;
  281. }
  282.  
  283. static inline void
  284. save_rle_decoder (FILE        *fp,
  285.           const gchar *macro_name,
  286.           const gchar *s_uint,
  287.           const gchar *s_uint_8,
  288.           guint        n_ch)
  289. {
  290.   fprintf (fp, "#define %s_RUN_LENGTH_DECODE(image_buf, rle_data, size, bpp) do \\\n",
  291.        macro_name);
  292.   fprintf (fp, "{ %s __bpp; %s *__ip; const %s *__il, *__rd; \\\n", s_uint, s_uint_8, s_uint_8);
  293.   fprintf (fp, "  __bpp = (bpp); __ip = (image_buf); __il = __ip + (size) * __bpp; \\\n");
  294.  
  295.   fprintf (fp, "  __rd = (rle_data); if (__bpp > 3) { /* RGBA */ \\\n");
  296.  
  297.   fprintf (fp, "    while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
  298.   fprintf (fp, "      if (__l & 128) { __l = __l - 128; \\\n");
  299.   fprintf (fp, "        do { memcpy (__ip, __rd, 4); __ip += 4; } while (--__l); __rd += 4; \\\n");
  300.   fprintf (fp, "      } else { __l *= 4; memcpy (__ip, __rd, __l); \\\n");
  301.   fprintf (fp, "               __ip += __l; __rd += __l; } } \\\n");
  302.  
  303.   fprintf (fp, "  } else { /* RGB */ \\\n");
  304.  
  305.   fprintf (fp, "    while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
  306.   fprintf (fp, "      if (__l & 128) { __l = __l - 128; \\\n");
  307.   fprintf (fp, "        do { memcpy (__ip, __rd, 3); __ip += 3; } while (--__l); __rd += 3; \\\n");
  308.   fprintf (fp, "      } else { __l *= 3; memcpy (__ip, __rd, __l); \\\n");
  309.   fprintf (fp, "               __ip += __l; __rd += __l; } } \\\n");
  310.  
  311.   fprintf (fp, "  } } while (0)\n");
  312. }
  313.  
  314. static inline guint
  315. save_uchar (FILE   *fp,
  316.         guint   c,
  317.         guint8  d,
  318.         Config *config)
  319. {
  320.   static guint8 pad = 0;
  321.  
  322.   if (c > 74)
  323.     {
  324.       if (!config->use_macros)
  325.     {
  326.       fprintf (fp, "\"\n  \"");
  327.       c = 3;
  328.     }
  329.       else
  330.     {
  331.       fprintf (fp, "\"\n \"");
  332.       c = 2;
  333.     }
  334.     }
  335.   if (d < 33 || d > 126)
  336.     {
  337.       fprintf (fp, "\\%o", d);
  338.       c += 1 + 1 + (d > 7) + (d > 63);
  339.       pad = d < 64;
  340.  
  341.       return c;
  342.     }
  343.   
  344.   if (d == '\\')
  345.     {
  346.       fputs ("\\\\", fp);
  347.       c += 2;
  348.     }
  349.   else if (d == '"')
  350.     {
  351.       fputs ("\\\"", fp);
  352.       c += 2;
  353.     }
  354.   else if (pad && d >= '0' && d <= '9')
  355.     {
  356.       fputs ("\"\"", fp);
  357.       fputc (d, fp);
  358.       c += 3;
  359.     }
  360.   else
  361.     {
  362.       fputc (d, fp);
  363.       c += 1;
  364.     }
  365.   pad = 0;
  366.   
  367.   return c;
  368. }
  369.  
  370. static gint
  371. save_image (Config *config,
  372.         gint32  image_ID,
  373.         gint32  drawable_ID)
  374. {
  375.   GimpDrawable *drawable         = gimp_drawable_get (drawable_ID);
  376.   GimpImageType drawable_type = gimp_drawable_type (drawable_ID);
  377.   GimpPixelRgn pixel_rgn;
  378.   gchar *s_uint_8, *s_uint_32, *s_uint, *s_char, *s_null;
  379.   FILE *fp;
  380.   guint c;
  381.   gchar *macro_name;
  382.   guint8 *img_buffer, *img_buffer_end;
  383.  
  384.   fp = fopen (config->file_name, "w");
  385.   if (!fp)
  386.     return FALSE;
  387.  
  388.   gimp_pixel_rgn_init (&pixel_rgn, drawable,
  389.                0, 0, drawable->width, drawable->height, FALSE, FALSE);
  390.  
  391.   if (1)
  392.     {
  393.       guint8 *data, *p;
  394.       gint x, y, pad, n_bytes, bpp;
  395.  
  396.       bpp = config->alpha ? 4 : 3;
  397.       n_bytes = drawable->width * drawable->height * bpp;
  398.       pad = drawable->width * drawable->bpp;
  399.       if (config->use_rle)
  400.     pad = MAX (pad, 130 + n_bytes / 127);
  401.       data = g_new (guint8, pad + n_bytes);
  402.       p = data + pad;
  403.       for (y = 0; y < drawable->height; y++)
  404.     {
  405.       gimp_pixel_rgn_get_row (&pixel_rgn, data, 0, y, drawable->width);
  406.       if (config->alpha)
  407.         for (x = 0; x < drawable->width; x++)
  408.           {
  409.         guint8 *d = data + x * drawable->bpp;
  410.         gdouble alpha = drawable_type == GIMP_RGBA_IMAGE ? d[3] : 0xff;
  411.         
  412.         alpha *= config->opacity / 100.0;
  413.         *(p++) = d[0];
  414.         *(p++) = d[1];
  415.         *(p++) = d[2];
  416.         *(p++) = alpha + 0.5;
  417.           }
  418.       else
  419.         for (x = 0; x < drawable->width; x++)
  420.           {
  421.         guint8 *d = data + x * drawable->bpp;
  422.         gdouble alpha = drawable_type == GIMP_RGBA_IMAGE ? d[3] : 0xff;
  423.         
  424.         alpha *= config->opacity / 25600.0;
  425.         *(p++) = 0.5 + alpha * (gdouble) d[0];
  426.         *(p++) = 0.5 + alpha * (gdouble) d[1];
  427.         *(p++) = 0.5 + alpha * (gdouble) d[2];
  428.           }
  429.     }
  430.       img_buffer = data + pad;
  431.       if (config->use_rle)
  432.     {
  433.       img_buffer_end = rl_encode_rgbx (data, img_buffer,
  434.                        img_buffer + n_bytes, bpp);
  435.       img_buffer = data;
  436.     }
  437.       else
  438.     img_buffer_end = img_buffer + n_bytes;
  439.     }
  440.  
  441.   if (!config->use_macros && config->glib_types)
  442.     {
  443.       s_uint_8 =  "guint8 ";
  444.       s_uint_32 = "guint32";
  445.       s_uint  =   "guint  ";
  446.       s_char =    "gchar  ";
  447.       s_null =    "NULL";
  448.     }
  449.   else if (!config->use_macros)
  450.     {
  451.       s_uint_8 =  "unsigned char";
  452.       s_uint_32 = "unsigned int ";
  453.       s_uint =    "unsigned int ";
  454.       s_char =    "char         ";
  455.       s_null =    "(char*) 0";
  456.     }
  457.   else if (config->use_macros && config->glib_types)
  458.     {
  459.       s_uint_8 =  "guint8";
  460.       s_uint_32 = "guint32";
  461.       s_uint  =   "guint";
  462.       s_char =    "gchar";
  463.       s_null =    "NULL";
  464.     }
  465.   else /* config->use_macros && !config->glib_types */
  466.     {
  467.       s_uint_8 =  "unsigned char";
  468.       s_uint_32 = "unsigned int";
  469.       s_uint =    "unsigned int";
  470.       s_char =    "char";
  471.       s_null =    "(char*) 0";
  472.     }
  473.   macro_name = g_strdup (config->prefixed_name);
  474.   g_strup (macro_name);
  475.   
  476.   fprintf (fp, "/* GIMP %s C-Source image dump %s(%s) */\n\n",
  477.        config->alpha ? "RGBA" : "RGB",
  478.        config->use_rle ? "1-byte-run-length-encoded " : "",
  479.        g_basename (config->file_name));
  480.  
  481.   if (config->use_rle && !config->use_macros)
  482.     save_rle_decoder (fp,
  483.               macro_name,
  484.               config->glib_types ? "guint" : "unsigned int",
  485.               config->glib_types ? "guint8" : "unsigned char",
  486.               config->alpha ? 4 : 3);
  487.  
  488.   if (!config->use_macros)
  489.     {
  490.       fprintf (fp, "static const struct {\n");
  491.       fprintf (fp, "  %s\t width;\n", s_uint);
  492.       fprintf (fp, "  %s\t height;\n", s_uint);
  493.       fprintf (fp, "  %s\t bytes_per_pixel; /* 3:RGB, 4:RGBA */ \n", s_uint);
  494.       if (config->use_comment)
  495.     fprintf (fp, "  %s\t*comment;\n", s_char);
  496.       fprintf (fp, "  %s\t %spixel_data[",
  497.            s_uint_8,
  498.            config->use_rle ? "rle_" : "");
  499.       if (config->use_rle)
  500.     fprintf (fp, "%u + 1];\n", (guint) (img_buffer_end - img_buffer));
  501.       else
  502.     fprintf (fp, "%u * %u * %u + 1];\n",
  503.          drawable->width,
  504.          drawable->height,
  505.          config->alpha ? 4 : 3);
  506.       fprintf (fp, "} %s = {\n", config->prefixed_name);
  507.       fprintf (fp, "  %u, %u, %u,\n",
  508.            drawable->width,
  509.            drawable->height,
  510.            config->alpha ? 4 : 3);
  511.     }
  512.   else /* use macros */
  513.     {
  514.       fprintf (fp, "#define %s_WIDTH (%u)\n",
  515.            macro_name, drawable->width);
  516.       fprintf (fp, "#define %s_HEIGHT (%u)\n",
  517.            macro_name, drawable->height);
  518.       fprintf (fp, "#define %s_BYTES_PER_PIXEL (%u) /* 3:RGB, 4:RGBA */\n",
  519.            macro_name, config->alpha ? 4 : 3);
  520.     }
  521.   if (config->use_comment && !config->comment)
  522.     {
  523.       if (!config->use_macros)
  524.     fprintf (fp, "  %s,\n", s_null);
  525.       else /* use macros */
  526.     fprintf (fp, "#define %s_COMMENT (%s)\n", macro_name, s_null);
  527.     }
  528.   else if (config->use_comment)
  529.     {
  530.       gchar *p = config->comment - 1;
  531.       
  532.       if (config->use_macros)
  533.     fprintf (fp, "#define %s_COMMENT \\\n", macro_name);
  534.       fprintf (fp, "  \"");
  535.       while (*(++p))
  536.     if (*p == '\\')
  537.       fprintf (fp, "\\\\");
  538.     else if (*p == '"')
  539.       fprintf (fp, "\\\"");
  540.     else if (*p == '\n' && p[1])
  541.       fprintf (fp, "\\n\"%s\n  \"",
  542.            config->use_macros ? " \\" : "");
  543.     else if (*p == '\n')
  544.       fprintf (fp, "\\n");
  545.     else if (*p == '\r')
  546.       fprintf (fp, "\\r");
  547.     else if (*p == '\b')
  548.       fprintf (fp, "\\b");
  549.     else if (*p == '\f')
  550.       fprintf (fp, "\\f");
  551.     else if (*p >= 32 && *p <= 126)
  552.       fprintf (fp, "%c", *p);
  553.     else
  554.       fprintf (fp, "\\%03o", *p);
  555.       if (!config->use_macros)
  556.     fprintf (fp, "\",\n");
  557.       else /* use macros */
  558.     fprintf (fp, "\"\n");
  559.     }
  560.   if (config->use_macros)
  561.     {
  562.       fprintf (fp, "#define %s_%sPIXEL_DATA ((%s*) %s_%spixel_data)\n",
  563.            macro_name,
  564.            config->use_rle ? "RLE_" : "",
  565.            s_uint_8,
  566.            macro_name,
  567.            config->use_rle ? "rle_" : "");
  568.       if (config->use_rle)
  569.     save_rle_decoder (fp,
  570.               macro_name,
  571.               s_uint,
  572.               s_uint_8,
  573.               config->alpha ? 4 : 3);
  574.       fprintf (fp, "static const %s %s_%spixel_data[",
  575.            s_uint_8,
  576.            macro_name,
  577.            config->use_rle ? "rle_" : "");
  578.       if (config->use_rle)
  579.     fprintf (fp, "%u] =\n", (guint) (img_buffer_end - img_buffer));
  580.       else
  581.     fprintf (fp, "%u * %u * %u + 1] =\n",
  582.          drawable->width,
  583.          drawable->height,
  584.          config->alpha ? 4 : 3);
  585.       fprintf (fp, "(\"");
  586.       c = 2;
  587.     }
  588.   else
  589.     {
  590.       fprintf (fp, "  \"");
  591.       c = 3;
  592.     }
  593.   switch (drawable_type)
  594.     {
  595.     case GIMP_RGB_IMAGE:
  596.     case GIMP_RGBA_IMAGE:
  597.       do
  598.     c = save_uchar (fp, c, *(img_buffer++), config);
  599.       while (img_buffer < img_buffer_end);
  600.       break;
  601.     default:
  602.       g_warning ("unhandled drawable type (%d)", drawable_type);
  603.       return FALSE;
  604.     }
  605.   if (!config->use_macros)
  606.     fprintf (fp, "\",\n};\n\n");
  607.   else /* use macros */
  608.     fprintf (fp, "\");\n\n");
  609.   
  610.   fclose (fp);
  611.   
  612.   gimp_drawable_detach (drawable);
  613.   
  614.   return TRUE;
  615. }
  616.  
  617. static GtkWidget *prefixed_name;
  618. static GtkWidget *centry;
  619. static gboolean   do_save = FALSE;
  620.  
  621. static void
  622. save_dialog_ok_callback (GtkWidget *widget,
  623.              gpointer   data)
  624. {
  625.   do_save = TRUE;
  626.  
  627.   config.prefixed_name =
  628.     g_strdup (gtk_entry_get_text (GTK_ENTRY (prefixed_name)));
  629.   config.comment = g_strdup (gtk_entry_get_text (GTK_ENTRY (centry)));
  630.  
  631.   gtk_widget_destroy (GTK_WIDGET (data));
  632. }
  633.  
  634. static gboolean
  635. run_save_dialog    (Config *config)
  636. {
  637.   GtkWidget *dialog;
  638.   GtkWidget *vbox;
  639.   GtkWidget *table;
  640.   GtkWidget *toggle;
  641.   GtkObject *adj;
  642.   
  643.   dialog = gimp_dialog_new (_("Save as C-Source"), "csource",
  644.                 gimp_standard_help_func, "filters/csource.html",
  645.                 GTK_WIN_POS_MOUSE,
  646.                 FALSE, TRUE, FALSE,
  647.  
  648.                 _("OK"), save_dialog_ok_callback,
  649.                 NULL, NULL, NULL, TRUE, FALSE,
  650.                 _("Cancel"), gtk_widget_destroy,
  651.                 NULL, 1, NULL, FALSE, TRUE,
  652.  
  653.                 NULL);
  654.  
  655.   gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
  656.               GTK_SIGNAL_FUNC (gtk_main_quit),
  657.               NULL);
  658.  
  659.  
  660.   vbox = gtk_vbox_new (FALSE, 2);
  661.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  662.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
  663.   gtk_widget_show (vbox);
  664.  
  665.   table = gtk_table_new (2, 2, FALSE);
  666.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  667.   gtk_table_set_row_spacings (GTK_TABLE (table), 4);
  668.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  669.   gtk_widget_show (table);
  670.  
  671.   /* Prefixed Name
  672.    */
  673.   prefixed_name = gtk_entry_new ();
  674.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  675.                  _("Prefixed Name:"), 1.0, 0.5,
  676.                  prefixed_name, 1, FALSE);
  677.   gtk_entry_set_text (GTK_ENTRY (prefixed_name),
  678.               config->prefixed_name ? config->prefixed_name : "");
  679.   
  680.   /* Comment Entry
  681.    */
  682.   centry = gtk_entry_new ();
  683.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  684.                  _("Comment:"), 1.0, 0.5,
  685.                  centry, 1, FALSE);
  686.   gtk_entry_set_text (GTK_ENTRY (centry),
  687.               config->comment ? config->comment : "");
  688.  
  689.   /* Use Comment
  690.    */
  691.   toggle = gtk_check_button_new_with_label (_("Save Comment to File"));
  692.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  693.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  694.                 config->use_comment);
  695.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  696.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  697.               &config->use_comment);
  698.   gtk_widget_show (toggle);
  699.  
  700.   /* GLib types
  701.    */
  702.   toggle = gtk_check_button_new_with_label (_("Use GLib Types (guint8*)"));
  703.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  704.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  705.                 config->glib_types);
  706.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  707.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  708.               &config->glib_types);
  709.   gtk_widget_show (toggle);
  710.  
  711.   /* Use Macros
  712.    */
  713.   toggle = gtk_check_button_new_with_label (_("Use Macros instead of Struct"));
  714.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  715.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  716.                 config->use_macros);
  717.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  718.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  719.               &config->use_macros);
  720.   gtk_widget_show (toggle);
  721.  
  722.   /* Use RLE
  723.    */
  724.   toggle = gtk_check_button_new_with_label (_("Use 1 Byte Run-Length-Encoding"));
  725.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  726.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  727.                 config->use_rle);
  728.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  729.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  730.               &config->use_rle);
  731.   gtk_widget_show (toggle);
  732.  
  733.   /* Alpha
  734.    */
  735.   toggle = gtk_check_button_new_with_label (_("Save Alpha Channel (RGBA/RGB)"));
  736.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  737.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  738.                 config->alpha);
  739.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  740.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  741.               &config->alpha);
  742.   gtk_widget_show (toggle);
  743.  
  744.   /* Max Alpha Value
  745.    */
  746.   table = gtk_table_new (1, 3, FALSE);
  747.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  748.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  749.   gtk_widget_show (table);
  750.  
  751.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  752.                   _("Opacity:"), 100, 0,
  753.                   config->opacity, 0, 100, 1, 10, 1,
  754.                   TRUE, 0, 0,
  755.                   FALSE, FALSE);
  756.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  757.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  758.               &config->opacity);
  759.  
  760.   gtk_widget_show (dialog);
  761.   
  762.   gtk_main ();
  763.   gdk_flush ();
  764.   
  765.   if (!config->prefixed_name || !config->prefixed_name[0])
  766.     config->prefixed_name = "tmp";
  767.   if (config->comment && !config->comment[0])
  768.     config->comment = NULL;
  769.  
  770.   return do_save;
  771. }
  772.